/*

Copyright (C) 2007 Thomas Geiger (tom.geiger@gmail.com)

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

*/


#include "GassServer.h"

namespace globus_server {

static const int DFLT_PORT = 10001;

static globus_mutex_t mutex;
static globus_cond_t cond;
static bool isDone;

void cb_done() {
	globus_mutex_lock(&mutex);
	isDone = true;
	globus_cond_signal(&cond);
}
	
GassServer::GassServer() {
	globus_module_activate(GLOBUS_GASS_TRANSFER_MODULE);
	globus_module_activate(GLOBUS_GASS_SERVER_EZ_MODULE);
	listenPort = DFLT_PORT;
	
	// let s define options for our GASS server
	server_ez_opts = 0UL;
	
	//Files openfor writing will be written a line at a time
	//so multiple writers can access them safely.
	server_ez_opts |= GLOBUS_GASS_SERVER_EZ_LINE_BUFFER;
	
	//URLs that have ~ character, will be expanded to the home
	//directory of the user who is running the server
	server_ez_opts |= GLOBUS_GASS_SERVER_EZ_TILDE_EXPAND;
	
	//URLs that have ~user character, will be expanded to the home
	//directory of the user on the server machine
	server_ez_opts |= GLOBUS_GASS_SERVER_EZ_TILDE_USER_EXPAND;
	
	//"get" requests will be fullfilled
	server_ez_opts |= GLOBUS_GASS_SERVER_EZ_READ_ENABLE;
	
	//"put" requests will be fullfilled
	server_ez_opts |= GLOBUS_GASS_SERVER_EZ_WRITE_ENABLE;
	
	// for put requets on /dev/stdout will be redirected to the standard
	// output stream of the gass server
	server_ez_opts |= GLOBUS_GASS_SERVER_EZ_STDOUT_ENABLE;
	
	// for put requets on /dev/stderr will be redirected to the standard
	// output stream of the gass server
	server_ez_opts |= GLOBUS_GASS_SERVER_EZ_STDERR_ENABLE;
	
	// "put requests" to the URL https://host/dev/globus_gass_client_shutdown
	// will cause the callback function to be called. this allows
	// the GASS client to communicate shutdown requests to the server
	server_ez_opts |= GLOBUS_GASS_SERVER_EZ_CLIENT_SHUTDOWN_ENABLE;
	
}

GassServer::~GassServer() {
	if (isRunning()) {
		stop();
	}
	globus_module_deactivate(GLOBUS_GASS_SERVER_EZ_MODULE);
	globus_module_activate(GLOBUS_GASS_TRANSFER_MODULE);
}

bool GassServer::start()
{	
	// Secure
	char* scheme;
	if (secure) {
		scheme="https";
	} else {
		scheme="http";
	}
		
	globus_gass_transfer_listenerattr_init(&attr, scheme);
	globus_gass_transfer_listenerattr_set_port(&attr, listenPort);
	
	globus_mutex_init(&mutex, GLOBUS_NULL);
	globus_cond_init(&cond, GLOBUS_NULL);
	
	isDone = false;
	
	int err = globus_gass_server_ez_init(&listener,
											&attr,
											scheme,
											GLOBUS_NULL, //purpose unknown
											server_ez_opts,
											cb_done); //or GLOBUS_NULL otherwise
	

	if((err != GLOBUS_SUCCESS)) {
		cerr << "Error: initializing GASS (" << err << ")" << endl;
		return false;
	}
	
	char* gass_server_url=globus_gass_transfer_listener_get_base_url(listener);
	cout << gass_server_url << endl;
	
	running = true;
	return true;
}

bool GassServer::stop()
{
	int err = globus_gass_server_ez_shutdown(listener);
	if((err != GLOBUS_SUCCESS)) {
		cerr << "Error: shutting down GASS (" << err << ")" << endl;
		return false;
	}
	isDone = false;
	running = false;
	listenPort = DFLT_PORT;
	
	return true;
}

bool GassServer::isRunning() {
	return running;
}

bool GassServer::setSecure(bool flag) {
	secure = flag;
}

bool GassServer::isSecure() {
	return secure;
}

bool GassServer::setPort(unsigned int port) {
	if (port > 65535) {
		cerr << "Invalid port: " << port << endl;
		return false;
	}
	listenPort = port;
}

unsigned int GassServer::getPort() {
	return listenPort;
}

}

